home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Game-Power
/
Amiga Game-Power.iso
/
anwendungen
/
gw print
/
structurebrowser_v1.3
/
sb.doc
< prev
next >
Wrap
Text File
|
1994-05-20
|
29KB
|
500 lines
Aug 13, 1988
Note:
The version of Structure Browser in this archive is 1.3, which differs
from the earlier release in supporting more structures (nearly all of
Intuition, plus some structures from the Layers and Graphics libraries),
and in supporting the TWM tiny window standard. The process for adding new
structures to those known by SB is as described below.
Nick Sullivan
Chris Zamara
Transactor for the Amiga
-----------------------------------------------------------------------------
(This article introducing Structure Browser appeared in The Transactor,
Volume 7 Issue 6. It has been edited slightly to reflect Version 1.2 of SB.)
The Transactor Structure Browser
By Chris Zamara and Nick Sullivan
- Your guided tour through the system
With this program and the information given in this article, you will
gain knowledge about your Amiga that you yearned for, but
couldn't find. This knowledge will make you a better programmer, almost
certainly making you more prosperous than you would have been otherwise.
With all of your extra money, you can buy more expensive computer
hardware and advance yourself even further.
You will be successful, and
that success will give you greater self-confidence. People will turn to
you for advice and you will help out many others who would like to be as
clever and successful as yourself. By helping these people, not only will
you gain deep personal fulfillment, but you will become quite popular and
well-liked, which certainly can't hurt your sex life.
Since so many
people will be looking up to you and following your advice, you will
wield quite a bit of power in the computer community and in your business
dealings in general. By feeling good about yourself, you will certainly
get into better physical shape and will definitely live longer - maybe up
to three hundred years!
In short, reading this article and typing in the
program at the end will give you knowledge, power, success and
prosperity. It will improve your sex life and give you greater self
esteem and a feeling of usefulness. You will be able to buy lots of
expensive computer hardware, and fast cars as well if you wish. You will
live longer.
But the choice is yours - read this article and make those
changes in your life, or skip past it and possibly never realize the
enormous potential that you know is inside of you.
* * * * * * * * * * * * * * * * * * * * * * * *
If you want to learn more about the Amiga's system structures, or you'd
like an easy way to look at vital data about programs while they execute,
you'll make good use of the Transactor Structure Browser.
If you read our Amiga programming article in the last issue, you learned
how important the various system structures are, since they are the key
to finding out about all entities known to the system, like tasks,
screens, windows, gadgets and the like. Structures in the Amiga are the
equivalent of a memory map on a single-tasking machine, since there are
no fixed memory locations on the Amiga.
The structure has a direct C-language implementation, but we can speak of
a structure template (the definition of the structure) independently of
a language. A structure is just the particular way that some data is
grouped. For example, a structure called 'X' might be defined as a word,
followed by a pointer to another structure 'X', followed by a pointer to
a structure 'Y', followed by a long word. By knowing a structure's
template and where in memory such a structure is stored, it is a simple
matter for the system or an application program to extract the data in
that structure.
What kind of information can we find in various structures throughout the
system's memory? Well, some interesting things are to be found, for
example, in the Intuition-managed structures. With the program presented
here, you'll be able to look at Screen, Window, and Gadget structures,
among others. Information about any program in the system can be gained by
looking at these structures, since everybody's windows, screens and gadgets
are maintained in a kind of network where they can be accessed via pointers
from other Screen, Window and Gadget structures. A pointer to the first
Screen is all that is needed to find everything else, and that is found in
the "IntuitionBase" structure, which, in turn, is found when the Intuition
library is opened by a call to the OpenLibrary() function. (OpenLibrary()
is in the Exec library, a pointer to which is found in memory location
000004, the only fixed location in the entire Amiga memory map. C-language
startup code opens the Exec library.) All programs that use Intuition have
their information in these structures, so through them you can learn
things about any task currently running in the system.
A screen structure contains everything Intuition needs to know about a
screen, like its size, title, number of bit-planes, a pointer to its
gadgets, flags describing what kind of screen it is, the colours it's
rendered in, etc. The screen structure points to a window structure for
the first window on the screen. A window structure has a pointer that can
point to another window structure, so that all windows in a screen are
linked together. If there is more than one screen in the system (unless
you have an application running that opens its own screen, the only
screen will be the Workbench screen), there will be a pointer in the first
screen structure to the next screen; any number of screens can be linked
together in this way. In a window structure you'll find the usual size
and colour information, along with an IDCMPFlags variable which describes
what messages Intuition is getting from that window.
A pointer to the first gadget in a linked list of gadgets can also be found
in the window structure. A gadget structure totally describes a gadget (a
simple way to get input from the user through the mouse) - its position,
size, type, imagery, etc. The gadget structure is set up by an application
before the structure is submitted to Intuition, so the values within
represent those that the programmer actually put into his code - in other
words, a peek into a program's gadget structure can give some insight into
how a program was written.
Other structures of interest that are not implemented in Version 1.2 of
Structure Browser: Image, Requester, Layer, Interrupt, MemChunk, MsgPort,
Message, Task, VSprite, AnimOb. (Many of these structures, like Task and
Interrupt, are difficult to monitor since the data within are constantly
changing.)
The key to finding the memory location of any structure is the Library Base
structures. Every shared library ("graphics.library", "intuition.library",
"layers.library", to name a few) has a library base structure that contains
pointers to structures of interest to routines in that library. The
structures form a kind of network, since you can reach structures through
pointers in other structures. In this network can be found every bit of
data that the system cares anything about; a direct link to the the
system's state of mind at any given moment. If we know the definitions for
the system structures (there are over a hundred of them altogether), we can
snoop around and discover anything we wish to know about what the system
knows. And in the Amiga, the system knows a lot, because application
software has to go through the system for just about anything it wants to
do.
The Structure Browser Program
The Structure Browser (SB from now on) makes it easy to snoop through many
of the structures in the system. You start with a list of the library base
structures; in the current version of the program, only IntuitionBase is
available. To display the contents of the library base structure, just move
the pointer to the library base name on the screen and press the left mouse
button. The library base structure will immediately be displayed, showing
each structure member's name (as defined in the standard Amiga header
files) and its data type. In the case of the IntuitionBase structure, all
members are pointers to other structures of importance; to display any of
these, just click on its name as usual. This process can be repeated again
in the new structure, to bring you to other structures of interest. You can
always get to the structure you came from by clicking on the "Previous
Level" gadget at the bottom left of the window. You can trace your steps as
far back as you want, since the program works recursively (the number of
levels deep you are is displayed in the heading at the top of the window).
Structures that contain more members than will fit on the window show the
first 16 members and display a gadget that says "(MORE)". You can go to the
next page of structure members by clicking on (MORE), and go to the
previous page by clicking on the "Previous Page" gadget. By going from
structure to structure in this manner, it is easy to view information
about programs that would be impossible to find out otherwise. For example
- what kind of gadgets are being used in that neat commercial program? Are
they gadgets at all? Did the programmer use a requester or a window for
that prompt? Just by mousing around with SB, you can find it all out!
The data type for each structure member is shown in the same way that the
members are declared in the C header files (the appropriate header file
must be compiled - using the #include statement - with any C program that
wants to refer to a system structure). These data types are standard in
Amiga code, because they are `typedefs' that are set up in the header file
"exec/types.h". The basic types are:
BYTE - signed 8-bit value (char)
UBYTE - unsigned 8-bit value (unsigned char)
SHORT - signed 16-bit value (short)
USHORT - unsigned 16-bit value (unsigned short)
LONG - signed 32-bit value (long)
ULONG - unsigned 32-bit value (unsigned long)
Pointers to any of the above are denoted as in standard C syntax, with an
asterisk (*). For example, a pointer to a SHORT would be denoted by SHORT *
in the type field. Structure members that are pointers to other structures
also use the C syntax; a pointer to a `Window' structure, for instance, is
denoted by `struct Window *'. A structure member that is an actual
structure, not a pointer to a structure, has no asterisk, and no value is
given (it is contained within the structure being viewed, whose address is
already shown).
Structure members that represent not pointers to other structures, but
actual data that may be of interest, are displayed in various ways depending
on their nature. These data can be simple numbers, like those giving a
window's LeftEdge, TopEdge, Width and Height. The item of interest might be
a byte, word or longword containing flags of some sort, like the flags
indicating a window or gadget type. Or the data you're concerned with might
just be an area of memory that contains a table of some sort or describes a
graphic image. Simple data values, like LefEdge, etc. are shown in black on
the SB window. Such structure members cannot be used to bring up any further
information by pointing on them and clicking - nothing will happen if you do
so. They are just what they appear; a number for you to see. The values in
black are often just what you want to find out after getting to a structure
of interest. When one of these values is used for containing flags of some
sort, it is treated differently: you can click on it to get a list of what
flags are set. An example might be a "smart refresh" window with sizing,
close and drag system gadgets. The "Flags" member of such a window's
structure, when selected, would show:
WINDOWDRAG WINDOWSIZING WINDOWCLOSE SMART_REFRESH
(Like the member names, the flag names are those defined in the standard
header files used for C or assembler program development.)
Another form of specialized output in SB is the hex dump. When a
structure member is an array of values or a pointer to an area of memory
like a bit-plane or image data, clicking on the member name causes a hex
dump of the data to be displayed. If the data type is specified in the
structure template, the data size is taken into account in the hex dump -
the hex values are shown as either bytes, words, or long words.
A Sample Tour
On paper, the process may sound rather involved, but using SB is a breeze.
Here's an example of how you could find out the type of gadget used by a
program that is currently running in the system. Let's use as an example
the editor on which this article is being written - we'll take a look at
the structure for this program's `page up' gadget to see how it is set up.
First, we have to run SB. That's not hard: type `sb' from the CLI. (or `run
sb' if you want to keep the CLI available for launching other tasks while
SB is running). SB will bring up a window that is the full width of the
screen, but isn't full height, leaving a bit of the WorkBench screen
visible at the top. On the window you will be prompted to select a library
structure. Since only one choice is available in this version of the
program, the decision isn't difficult: select "Intuition" by pointing with
the mouse and clicking the left button. After clicking, a list of the
"IntuitionBase" structure members will be displayed, with their types and
values shown on the right. All members are pointers to the indicated
structures, and the top two are parenthesized, meaning that those structure
types are not available in this version of the program. To keep the
magazine listing reasonably short, we only implemented a few key structure
types; pointers to unimplemented structures are parenthesized, and clicking
on them has no effect.
Now, on with our travels to the gadget structure of interest. Since the
program we're interested in has a window on the WorkBench screen, we must
get to that screen's structure first. We can get there by clicking on the
"ActiveScreen" member in the IntuitionBase structure, since the active
screen - the one we're currently working on - is the WorkBench screen. One
click, and up comes the first page of the structure members in the WorkBench
screen structure. You can tell you've got the right screen by looking at the
member called "Title"; to the right it should say "Workbench Screen". To see
more screen members, you can click on the "(MORE)" gadget that has appeared
at the bottom of the window, and then click on "Previous Page" to get back.
The second member of the screen structure is called "FirstWindow", and it
points to the first window structure in a linked list containing all windows
on the screen.
Click on "FirstWindow" and a window structure will be displayed. It may not
be the window we're looking for, in fact it might be the window belonging
to SB itself. The "Title" member will tell you what window you're looking
at, since it will say exactly what is on the title bar of the corresponding
window. You'll also notice other items of interest in this structure, like
the window's dimensions and the flags set for the window. Try clicking on
the "Flags" member to show the window flags. Even if you're not familiar
with Intuition programming, the names of the flags should suggest their
purpose. Now, to get to the next window structure in the list, just click
on the first member of the window structure, the one called "NextWindow".
You'll now have the structure for the next window displayed - continue
chaining through windows like this until you get to the one you want. For
our sample structure tour, we would stop when we got to the window
belonging the text editor.
Now that we've found the window structure we want, let's look for a pointer
to the gadget list attached to the window. There's nothing like that on the
first page, so click the "(MORE)" gadget to see more window members. About
half way down is the member "FirstGadget", which points to a gadget
structure (its type is `struct Gadget *', meaning a pointer to a Gadget
structure). Click there, and up comes the first in a linked list of gadget
structures for that window. By looking at the LeftEdge and Top variables,
you can see the position of the gadget on the screen. To go to the next
gadget structure in the list, just click on the first member, "NextGadget".
You can chain through the program's entire gadget list this way, stopping
when you wish to examine the flag variables "Flags, "Activation", or
"GadgetType". GadgetType will tell you if the gadget is a BOOLGADGET
(boolean), PROPGADGET (proportional), or STRGADGET (string). Eventually, we
get to a gadget with its TopEdge at 20, and its LeftEdge at -16. Since the
GRELRIGHT flag is set in the Flags variable, we know the LeftEdge value
indicates that the left edge of the gadget is 16 pixels to the left of the
window's right border. That's the `page up' gadget that we're looking for.
We can examine the Gadget structure to see exactly how we could create a
similar gadget in our own programs. (Using the same imagery as someone
else's gadget in your programs might be considered a violation of
copyright, but the current version of SB doesn't support Image structures
anyway so there'll be no "Don't try this at home, kids!" warning here.)
Structure Browser doesn't support all the system structures as it stands
now - there are just too many and the program would fill the entire
magazine. Rather, we have put in some of the more interesting Intuition
structures and we plan on adding more for version 2.0 of SB, which will be
found on The Transactor's first Amiga disk, and will be uploaded to
Compuserve's AmigaForum. The program is designed so that it is easy to add
new structures as you wish - if you have access to the "include" files for
development (or the listings of them in the ROM Kernal manual), it should
be easy for you to add whatever structures you're interested in to the
program. Information about doing this is given later in the article. SB is
public domain, so you're free to use and modify it as you wish; if you do
add new structures, though, please use the standard Amiga member names and
types exactly as they appear in the include files. We plan to see how far
the SB concept of system structure browsing can be taken - a few ideas for
enhancements are given later in this article.
Applications for SB
By now you've probably seen that SB is a great tool for learning about
the Amiga's internal data structures. But there are actually quite a few
good reasons to have SB around on your most-used disk - maybe even in the
C directory of your usual Workbench or development disk.
For one thing, SB makes a very handy reference to the structure templates
themselves. It's easier to bring up SB and click to a structure than to
look up that structure definition in the ROM Kernal manual. And if you
don't have the manual, it's easier than looking through lots of include
files. If you don't have the include files, it's the only way!
SB can also be used as a debugging tool: if your program is acting
strange, you can peek at Intuition's view of your windows, gadgets, etc.,
to make sure they are properly set up and linked together the way you
intended. You can look at these things at any time during your program's
execution to see what happens when certain actions are taken; kind of
like a trace, but only pertaining to the program's interaction with the
operating system.
Another benefit of SB is that you can use it to learn programming
techniques by looking at how other applications have set up their
structures to achieve certain effects. By investigating the structures of
known system entities, you can see what effect certain flags and variables
have on their behaviour. If you're curious about the tricks that some
program is using, just take a browse through its gadgets and windows. For
instance, did you know that Workbench uses a borderless, backdrop window
that lies on the Workbench screen just below the screen title? We didn't
either, until we used SB to look at the Workbench window structure. You
can get some good ideas from other people's use of Intuition's resources.
Future Versions of SB
Our main goal for SB is to eventually have it encompass all system
structures and flags. The program can be expected to grow in size
considerably, but it will be worth it for a total map of the system's
inner thoughts. But besides expanding in scope, there could also be more
flexibility in the ways that lowest-level data types are displayed. For
example, graphic data could be displayed not as a hex-dump, but as the
actual image that it defines. Some values, like the mouse's X and Y
coordinates that are found in a window structure, could be updated
frequently to give readings that are always up-to-date. The hex dump
should also display ASCII equivalents of the bytes. Perhaps a less
immediately-implemented feature will be the saving of image and BitMap
data to disk as IFF-format files. There should be a way to save any
structure and its current values to a file as well, perhaps as C or
assembler code for easy inclusion in your own programs. If anyone has any
good ideas, let us know. Or better yet, implement them - we don't want
all the glory for ourselves! (read: we don't want to do all the work
ourselves!)
Program Listing Notes
The C source for SB is broken into several files, each with its own purpose.
The mainline and general functions are in the file "sb.c". The intuition
calls and all functions dealing with the program's user interface is in the
file "sbio.c". The other files contain the individual routines to handle
different structure types. "sbwindow.c", "sbscreen.c", and "sbgadget.c"
contain the functions that handle the structures their names suggest.
"sbgfx.c" handles the graphics library-related structures, RastPort and
BitMap. In addition, a header file, "sb.h", contains various #define
statements and a structure definition - it should be stored in a
subdirectory called "header". All of these separate files can be compiled
with Manx Aztec C using "make" and the makefile provided. The makefile takes
advantage of Manx's pre-compiled header file capability to speed up
compilation by not having to re-compile "intuition.h" in each of the six
source files. If you are using this method, you can delete the #include at
the top of each source file as indicated in the comment. For users of
Lattice C, just compile all six files and link them normally - don't worry
about the makefile.
When entering the program, take extra care in entering the the `structdata'
arrays in each structure print function. The first character of each member
name is either a space, minus, or left parenthesis; it is important to use
the correct one. Also, if you use the wrong data size constant (like putting
in INTSIZE where it should be PTRSIZE), you will get bad results when you
try to display that structure, or worse yet, a software error.
NOTE: in version 1.2 (and later) of SB, a trap-handler is installed to
catch CPU exceptions and eliminate most software errors.
Program Notes
SB is quite useful as it stands, but you may want to modify it to
incorporate some other structures that you're interested in. If you do,
here is some explanation of the program to help you out. The specifics are
up to you; have a ball, hackers!
The principle behind SB is very simple. A specialized function exists for
each kind of structure. If a structure contains more members than will fit
on one page, there is a function for each subsequent page. The function is
passed a pointer to the structure (and an offset, in the case of
multiple-page structures), and it prints the structure's members, types and
values, then waits for input. (The actual output and input is handled by
functions in "sbio.c", but more on those later.) Depending on the member
selected by the user, an appropriate routine is called to print that
structure's members and again wait for input. It may be that a routine
calls itself, as when chaining through a linked list of like structures. In
any case, each selection brings the program one level of nesting deeper,
and the only way to go up a level is by the user clicking the "Previous
Level" or "Previous Page" gadget, causing the return from a function.
Besides functions that handle specific structures, there are the more
general output functions that display hex dumps or flags - these are in the
file "sb.c". The function used to tell the output function in "sbio.c" what
to display is called put(), and is also in "sb.c" - it is called by all the
structure output functions and is passed a pointer to the structure and a
pointer to an array of special "StructData" structures. Setting up this
array is the key to adding more structures to SB's repetoire.
A "StructData" structure is defined in the file "sb.h" seen in the listing.
It contains information that SB needs to know about a structure member: its
name, type, print option, and size. The name and type are just pointers to
strings for display. The print type is needed so that put() knows how to
print the member's value - as a byte, short, or long, signed or unsigned, or
as a string or pointer. See the put() function to see how the print codes
are interpreted. The other member of a struct StructData, the data size,
indicates the number of bytes used by the structure member. The constants
BYTESIZE, INTSIZE, and PTRSIZE are defined in "sb.h" to specify the common
sizes 1, 2, and 4. When the member is a structure (not a pointer to a
structure, but an instance of the structure itself), use the SZ macro
defined in "sb.h" to calculate the size of the structure, e.g. SZ(View)
instead of sizeof(struct View).
By looking at the functions PrWindow(), PrScreen(), and PrGadget() as
examples, you should have no difficulty adding the functions to display
system structures of your interest. If you add a new structure, you'll have
to allow the user to select it from another structure by removing the
parenthesis from around the member name and type. An opening parenthesis at
the start of a member name instead of a space prevents that member from
being selected by the user (doesn't make it a gadget). Just remove these
parenthesis from all functions whose structure contains a pointer to your
newly-implemented structure, and add a call to your new function in the
SWITCH statement. Again, refer to the functions mentioned above for
clarification.
In the print function for any new structure you've added to the program,
set up a static 'structdata' array of StructData structures (try saying
that three times quickly!) as in the other functions. Members names should
begin with a space for flags, arrays, or pointers to structures that
SB can handle (i.e. anything for which a print function exists), a minus
(-) for simple data elements that will be rendered in black and will not be
selectable by the user, or a parenthesis for pointers to structures that
are not supported by the program.
The output of members to the window and the input of a response from the
user is handled by the same function, GetChoice(). Selectable structure
members are implemented as Intuition gadgets that have no rendering other
than the associated IntuiText. An array of 16 IntuiText structures is set up
to contain the text for each line printed to the window. An array of 16
boolean gadgets, each pointing to a different IntuiText structure, is also
declared. Gadget structures also exist for the "Previous Level" and
"(MORE)" gadgets that appear on the window.
When GetChoice() is called, it calls Redisplay() to put up the structure
member names and build the required list of gadgets. Redisplay() first
removes all existing gadgets except the first in the gadget list, the
"Previous Level" gadget (BackGadg). Depending on the number of structure
members to be displayed, up to 16 passes through a loop are made to either
print an IntuiText or add the associated gadget to the gadget list. After
the loop, the "(MORE)" gadget (MoreGadg) is added if there are more than 16
structure members to display. Finally, a call to the Intuition function
RefreshGadgets() displays the gadget text on the window. After Redisplay()
has done it job, GetChoice() waits for an IDCMP (Intuition Direct
Communication Message Port) event, which will signify that the user has
selected a gadget. If the window close gadget was selected, CloseOut() is
called to close up libraries and the open window, then call exit() to fix
up the stack and return to CLI. if another gadget was selected, the
gadget's ID is returned to the caller of GetChoice(). The IDs of the
structure member gadgets are their ordinal values - 1 for the first and so
on. The "Previous Level" gadget has an ID of 0, and the "(MORE)" gadget's
ID is the constant MOREGADG, defined as 25 in "sb.h".
To SB 2.0 ... And Beyond!
As you've read, SB can be expected to expand well beyond its current
capabilities. If anyone adds new structures, flags, or features to SB, we
would be happy to incorporate the changes in the latest version for wide
public-domain distribution. We will play `keeper of the source' and attempt
to coordinate all improvements to maintain the latest, greatest SB which
will be uploaded to Compuserve and other services, and included on our
public-domain Amiga disks (probably available next issue).
Meanwhile, have fun picking Intuition's brains with SB 1.2, and we'll see
you next issue!